package com.mangguo.tingjian.account.rest;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mangguo.tingjian.account.dto.AuthorityDto;
import com.mangguo.tingjian.account.dto.LoginDto;
import com.mangguo.tingjian.common.Result;
import com.mangguo.tingjian.account.security.jwt.JWTFilter;
import com.mangguo.tingjian.account.security.jwt.TokenProvider;
import com.mangguo.tingjian.account.service.AuthorityService;
import com.mangguo.tingjian.account.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;

/**
 * Controller to authenticate users.
 */
@RestController
@RequestMapping("/authenticate")
@Slf4j
public class AuthenticationRestController {

   private final TokenProvider tokenProvider;

   private final AuthenticationManagerBuilder authenticationManagerBuilder;

   @Resource
   private AuthorityService authorityService;

   @Resource
   private UserService userService;

   public AuthenticationRestController(TokenProvider tokenProvider, AuthenticationManagerBuilder authenticationManagerBuilder) {
      this.tokenProvider = tokenProvider;
      this.authenticationManagerBuilder = authenticationManagerBuilder;
   }

   @PostMapping("/login")
   public Result<JWTToken> authorize(@Valid @RequestBody LoginDto loginDto) {

      UsernamePasswordAuthenticationToken authenticationToken =
         new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());

      Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
      SecurityContextHolder.getContext().setAuthentication(authentication);

      boolean rememberMe = (loginDto.isRememberMe() == null) ? false : loginDto.isRememberMe();
      String jwt = tokenProvider.createToken(authentication, rememberMe);

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt);
      //更新登录时间
      userService.updateLoginTime(loginDto.getUsername(), new Date());

      return Result.success(new JWTToken("Bearer " + jwt));
   }

   /**
    * 分配权限
    * @param authorityDto
    * @return
    */
   @PostMapping("/distribution")
   public Result<Boolean> distribution(@Valid @RequestBody AuthorityDto authorityDto){
      log.info("distribution permission to dept and role, authorityDto:{}", JSONObject.toJSONString(authorityDto));
      return Result.success(authorityService.distribution(authorityDto));
   }

   /**
    * 根据角色和部门获取权限
    * @param authorityDto
    * @return
    */
   @PostMapping("/get-authority")
   public Result<AuthorityDto> getAuthorityByDeptAndRole(@Valid @RequestBody AuthorityDto authorityDto){
      return Result.success(authorityService.getAuthority(authorityDto.getDeptId(), authorityDto.getRoleId()));
   }

   /**
    * Object to return as body in JWT Authentication.
    */
   static class JWTToken {

      private String idToken;

      JWTToken(String idToken) {
         this.idToken = idToken;
      }

      @JsonProperty("id_token")
      String getIdToken() {
         return idToken;
      }

      void setIdToken(String idToken) {
         this.idToken = idToken;
      }
   }
}
